log = __import__("logging").getLogger("plonetheme.apkntheme.browser")

import itertools
from Products.Five import BrowserView
from zope.component import getMultiAdapter
from zope.interface import implements
from Acquisition import aq_inner, aq_base, aq_parent
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.i18nl10n import ulocalized_time
from Products.CMFPlone import Batch
from plone.i18n.locales.countries import countries
from plone.app.layout.globals.interfaces import IViewView
from plone.memoize import ram
from plone.memoize.view import memoize
from plone.app.layout.navigation.navtree import buildFolderTree
from plone.app.layout.navigation.navtree import NavtreeStrategyBase

import pyquery
from plonetheme.apkntheme import APKNThemeMessageFactory as _, logger
from plonetheme.apkntheme.settings import *
from plonetheme.apkntheme.browser.syndication import random_string,\
                                    getFeedItems as getRSSItems
from plonetheme.apkntheme.utils.tools import checkURLExists

from apkn.resource.config import RESOURCESUBJECTS

from datetime import datetime
import re
from time import time
import logging

try:
    import json
except ImportError:
    import simplejson as json
    
pq = pyquery.PyQuery

def format_field(value):
    '''
    Format values as strings based on their type
    '''
    final_value = value
    if isinstance(value, list):
        final_value = ','.join(value)
    log.debug("Finished formatting value %s of type %s. Final Value @@ %s", str(value), type(value), final_value)
    return final_value


def compute_request_cache_key(method, browser_view):
    '''
    Compute cache key for news feeds. Path info is prepended to ensure
    unique keys are generated
    '''
    timeDiff = time()//CACHE_SECONDS_DEFAULT
    path_info = browser_view.request.environ.get('PATH_INFO')
    key = "%s:%s" %(str(timeDiff), path_info)
    logger.debug("DASHBOARD: computed cache key @@ %s", key)
    return key

def compute_cache_key_rss_parliaments(method, browser_view):
    '''
    Compute a cache key for the parliamentary news feed. 
    This is only required once.
    '''
    timeDiff = time()//CACHE_SECONDS_DEFAULT
    key = "%s:%s" %(str(timeDiff), CACHE_RSS_KEY_PARLIAMENTS)


class translatePanel(BrowserView):
    """
    Renders Macro Containing Translation Machinery
    """

class SearchContactDirectories(BrowserView):
    
    def searchResults(self, show_all = False):
        if self.searchSubmitted() and not show_all:
            search_text = self.getSearchParam(SEARCH_TEXT_PARAM)
            search_path = self.getSearchParam(SEARCH_PATH_PARAM)
            results = self.performSearch(search_text, search_path)
        else:
            results = self.performSearch()
        final_results = []
        for result in results:
            path = result.getPath()
            country = path.rsplit('/country-folders/')\
            [1].split('/')[0]
            country_caps = country.capitalize()
            
            country_path = COUNTRY_FOLDERS_PATH + country
            country_code = ''
            try:
                country_object = self.context.restrictedTraverse(country_path)
                if country_object:
                    country_code = getattr(country_object, COUNTRY_FOLDER_META, '')
            except:
                pass
            url = result.getURL()
            title = result.Title
            final_results.append({'link': url,
            'country': country_caps,
            'title': title,
            'country_code': country_code.upper()
            })
        sorted_final_results = sorted(final_results, 
        key = lambda v: v['country'])
        
        result_count = len(sorted_final_results)
        search_message = self.getSearchMessage(result_count)
        
        search_data = {'search_results': sorted_final_results, 
        'search_message': search_message}
        return search_data
    
    def getDataForMap(self):
        search_results = self.context.folderlistingFolderContents()
        #uniqify
        all_codes = [getattr(s, COUNTRY_FOLDER_META, '') for s in search_results]
        
        st = {}
        map(st.__setitem__, all_codes, [])
        unique_codes = st.keys()
        
        final_codes = [{'country_code': code.upper(),'links': [] } \
        for code in unique_codes]
        
        code_data = {}
        for res in search_results:
            c_code = getattr(res, COUNTRY_FOLDER_META, '').upper()
            if code_data.has_key(c_code):
                link_data = (res.absolute_url(), res['title'])
                code_data[c_code]['links'].append(link_data)
            else:
                link_list = list()
                link_data = (res.absolute_url(), res['title'])
                link_list.append(link_data)
                code_data[c_code] = {'links': link_list,
                'country': res['title']}
        
        map_data = json.dumps(final_codes)
        code_data_json = json.dumps(code_data)
        return u'window[\'dataForMap\'] = ' + map_data +\
        '; window[\'codeDataForMap\'] = ' + code_data_json

    def getGeoCodes(self):
        query_path = {'query': COUNTRY_FOLDERS_PATH, 'depth': 2}
        catalog = getToolByName(self.context, u'portal_catalog')
        country_folder_objects = self.context.folderlistingFolderContents()
        obj_data = []
 
        try:
            obj_data = [
            {'title': c.title, 
            'lat': c.geo_latitude, 
            'lng': c.geo_longitude, 
            'code': getattr(c, COUNTRY_FOLDER_META).upper()} 
            for c in country_folder_objects]
        except:
            logger.info("Could not load GeoData - Country Folders not yet GeoCoded")
        json_geo = json.dumps(obj_data)
        return u'window[\'geoCodes\']=%s' % json_geo
    
    def searchResultsAll(self):
        return self.searchResults(True)['search_results']
    
    def performSearch(self, search_text = None, search_location = None):
        current_object = aq_inner(self.context)
        catalog = self.context.portal_catalog
        search_path = '/'.join(current_object.getPhysicalPath())
        search_types = CONTACT_SEARCH_PORTAL_TYPES
        type_filter = {'query': search_types, 'operator': 'or'}
        
        query = {}
        query['meta_type'] = type_filter
        query['path'] = search_path
        query['review_state'] = u'published'
        if search_text:
            query['SearchableText'] = search_text
        if search_location:
            search_path = '/'.join((search_path, search_location))
            query['path'] = search_path
        logger.info("Performing catalog query with params %s", 
        query.__str__())
        results = catalog.searchResults(query)
        return results
    
    def searchSubmitted(self):
        submitted = False
        submit_button = self.request.form.get(SEARCH_BUTTON_PARAM, 
                                              False)
        if submit_button:
            submitted = True
        return submitted
    
    def getSearchParam(self, param_name):
        search_text = self.request.form.get(param_name, None)
        return search_text

    def getSearchMessage(self, result_count):
        country = self.getSearchParam(SEARCH_PATH_PARAM)
        if country:
            country = country.replace('-', ' ').title()
        else:
            country = _(u'all countries')
        search_text = self.getSearchParam(SEARCH_TEXT_PARAM)
        if not search_text:
            search_text = _(u'all directories')
        search_message = _(u'search_contacts_status_message',
        default = u'Your search for "${search_text}" in \
        "${country_folder}" yielded ${result_count} hits',
        mapping = {u'search_text': search_text, 
        u'country_folder': country,
        u'result_count': result_count}
        )
        return search_message 

    @ram.cache(compute_request_cache_key)
    def getCountryList(self):
        country_list = []
        context_object = aq_inner(self.context)
        object_ids = context_object.objectIds()
        selected_value = None
        if self.searchSubmitted():
            selected_value = self.getSearchParam(SEARCH_PATH_PARAM)
        for obj_id in object_ids:
            obj = None
            try:
                obj = getattr(context_object, obj_id)
            except:
                logger.error("Unable to extract info for object with id %s", obj_id)
            if obj:
                pre_selected_value = None
                if selected_value == obj_id:
                    pre_selected_value = u'selected'
                if hasattr(obj, COUNTRY_FOLDER_META):
                    country_list.append({'title': obj.Title(), 
                    'id': obj_id, 'selected': pre_selected_value})
        return country_list

class countryFolderContainer(BrowserView):
    '''
    View for country folders container
    #TODO: memoize
    '''
    
    def  getContextMenu(self):
        pass
    
    @ram.cache(compute_cache_key_rss_parliaments)
    def getFeedItems(self):
        all_items = []
        for feed in ANM_PARLIAMENT_FEEDS:
            rss_url = ANM_PARL_FEED_URL %(feed['id'], 
            DEFAULT_FEED_LANGUAGE)
            items = {}
            items['title'] = feed['title']
            items['news_url'] = ANM_PARL_NEWS_URL %(DEFAULT_FEED_LANGUAGE,
            feed['id'])
            set_items = []
            try:
                feed_content = pq(rss_url)
                feed_items = pq('item', pq(feed_content))
                for item in feed_items:
                    link = pq('link', pq(item))
                    title = pq('title', pq(item))
                    link_text = pq(link).text()
                    title_text = pq(title).text()
                    set_items.append({'title':title_text,'link': link_text})
                    if len(set_items) > FEED_ITEMS_COUNT_ROOT:
                        break
            except Exception, e:
                logger.error("Failed to load parliaments news feed %s.\
                 Error @@  %s", feed['id'], e.__str__())
            items['items'] = set_items
            items['has_items'] = bool(len(set_items))
            all_items.append(items)
        return all_items

    def getCountryListing(self):
        '''
        Return a list of country title and name from the
        in ../settings.py find COUNTRY_CONTEXT_MENU_ROOT
        '''
        container_object = aq_inner(self.context)
        listing = []
        filter_type = self.getRequestParam(PARAM_CONTENT_FILTER)
        filter_settings = COUNTRY_CONTEXT_MENU_ROOT[filter_type]
        
        obj_ids = container_object.objectIds()
        for obj_id in obj_ids:
            obj = None
            try:
                obj = getattr(container_object, obj_id)
                if not hasattr(obj, COUNTRY_FOLDER_META):
                    obj = None
            except Exception, e:
                logger.error("Failed to load object from country folder \
                with id %s. Error @@ %s", obj_id, e.__str__())
            if obj:
                CONTEXT_ID = obj.getId()
                CONTEXT_TITLE = obj.Title()
                CONTEXT_URL = obj.absolute_url()
                listing.append({'link': CONTEXT_URL, 
                'title': CONTEXT_TITLE})
        return listing

    def getRequestParam(self, paramName):
        param = self.request.form.get(paramName,None)
        return param
        
    def validateParam(self, paramName, filterValues):
        param = self.getRequestParam(paramName)
        if param in filterValues:
            return param
        else:
            return None

    def isUserAnonymous(self):
        pm = getToolByName(self.context, 'portal_membership')
        anon = pm.isAnonymousUser()
        return anon

    def hasContentFilter(self):
        has_content_filter = True
        if self.validateParam(PARAM_CONTENT_FILTER, 
                                ALLOWED_DASHBOARD_ACTIONS_ROOT) is None:
                                    has_content_filter = False
        return has_content_filter

    def getSiblingsOfType(self, meta_type, container, fields):
        item_list = []
        object_ids = container.objectIds()
        for oid in object_ids:
            obj = getattr(container, oid)
            if obj.meta_type in meta_type:
                title = obj.Title()
                link = obj.absolute_url()
                field_data = {}
                if fields:
                    for field_name in fields:
                        field_value = getattr(obj, field_name)
                        field_value = format_field(field_value)
                        field_data[field_name] = field_value
                item_list.append((title, link, field_data))
            if len(item_list) >= RECENT_ITEM_COUNT:
                break
        return item_list

    def searchResults(self, meta_type, fields = None):
        '''
        Search current context for objects of a particular type
        '''
        items = []
        current_object = aq_inner(self.context)
        current_path = '/'.join(current_object.getPhysicalPath())
        portal_catalog = getToolByName(self.context, 'portal_catalog')
        search_results = portal_catalog(
            meta_type =  meta_type,
            path = current_path,
            limit = RECENT_ITEM_COUNT,
            sort_on = 'Date',
            review_state = 'published'
        )
        if search_results:
            for result in search_results:
                field_data = {}
                if fields:
                    obj = result.getObject()
                    for field_name in fields:
                        field_value = getattr(obj, field_name)
                        final_value = format_field(field_value)
                        field_data[field_name] = final_value
                itm = (result.Title, result.getURL(), field_data)
                items.append(itm)
        return items

    def getSiblingsFromLocation(self, meta_type, location, which, fields):
        item_list = []
        current_object = aq_inner(self.context)
        portal_url = getToolByName(self.context, 'portal_url')
        workflow_tool = getToolByName(self.context, 'portal_workflow')
        portal = portal_url.getPortalObject()
        try:
            real_location = eval(location)
        except:
            real_location = location
        container = portal.restrictedTraverse(real_location)
        if container:
            if which == ITEMS_RECENT:
                object_ids = container.objectIds()
                for obj_id in object_ids:
                    obj = getattr(container, obj_id)
                    publish_state = workflow_tool.getInfoFor(obj, \
                    'review_state')
                    if (publish_state == u'published')\
                    and (obj.portal_type == meta_type):
                        field_data = {}
                        if fields:
                            for field_name in fields:
                                field_value = getattr(obj, field_name)
                                field_value = format_field(field_value)
                                field_data[field_name] = field_value
                        item_list.append((obj.title, obj.absolute_url(),
                        field_data))
                    if len(item_list) >= RECENT_ITEM_COUNT_ROOT:
                        break
        return item_list

    def  getRecentItems(self):
        """ 
        List the recent content in Main Country Page 
        Based on recent item filters and filter methods
        """
        current_object = aq_inner(self.context)
        item_listing = []
        
        for filter_item in RECENT_ITEM_FILTERS_ROOT:
            this_list = dict()
            this_list['id'] = filter_item[0]
            this_list['title'] = filter_item[3]
            this_list['rend_id'] = filter_item[4]
            this_list['extra_fields'] = filter_item[5]
            this_list['section_header'] = filter_item[6]
            extra_fields = this_list['extra_fields']
            #get all items for current type
            method, ident = filter_item[2].split(':')
            meta_type = filter_item[1]
            if method == 'SKIP':
                this_list['items'] = []
            elif method == "HERE":
                this_list['items'] = \
                self.getSiblingsOfType(meta_type, current_object,
                extra_fields)
            elif method == 'LOOKUP':
                this_list['items'] = \
                self.getSiblingsFromLocation(meta_type, ident, ITEMS_RECENT,
                extra_fields)
            elif method == 'SEARCH':
                this_list['items'] = \
                self.searchResults(meta_type, extra_fields)
            else:
                this_list['items'] = []
            item_listing.append(this_list)
        return item_listing

class countryFolderMain(BrowserView):
    """
    Country folder dynamic browser view
    Filters by content type or display dashboard
    of items
    #TODO memoize, add menus to interface
    """
    implements(IViewView)
    
    def getRequestParam(self, paramName):
        param = self.request.form.get(paramName,None)
        return param
        
    def validateParam(self, paramName, filterValues):
        param = self.getRequestParam(paramName)
        if param in filterValues:
            return param
        else:
            return None

    def isUserAnonymous(self):
        pm = getToolByName(self.context, 'portal_membership')
        anon = pm.isAnonymousUser()
        return anon

    def getContextMenu(self):
        '''
        Gets the menu items for country folder content types with
        the option to get a link to a particular item and optional
        display based on user login status.
        See: COUNTRY_CONTEXT_MENU defined in ../settings.py
        '''
        current_object = aq_inner(self.context)
        CONTEXT_ID = current_object.id
        CONTEXT_TITLE = current_object.Title()
        CONTEXT_COUNTRY_CODE = current_object.get(COUNTRY_FOLDER_META,\
                                                                    '')
        if CONTEXT_COUNTRY_CODE:
            CONTEXT_COUNTRY_CODE += '.'
        menu_items = []
        for cmenu in COUNTRY_CONTEXT_MENU:
            link = cmenu[1]
            link = link.replace(u'@@CONTEXT_ID', CONTEXT_ID)
            link = link.replace(u'@@CONTEXT_TITLE', CONTEXT_TITLE)
            link = link.replace(u'@@CONTEXT_COUNTRY_CODE', \
                                                CONTEXT_COUNTRY_CODE)
            
            if cmenu[2]:
                content_items = self.getSiblingsOfType(cmenu[2], 
                current_object)
                if len(content_items) == 1:
                    link = content_items[0][1]
            
            show = cmenu[3]
            
            
            if cmenu[5]:
                exists = checkURLExists(link)
            else:
                exists = True
            if (not show) and (self.isUserAnonymous()):
                pass
            else:
                menu_items.append({'title': cmenu[0], 'link': link, 'exists': exists})
        return menu_items

    def hasContentFilter(self):
        has_content_filter = True
        if self.validateParam(PARAM_CONTENT_FILTER, 
                                ALLOWED_DASHBOARD_ACTIONS) is None:
                                    has_content_filter = False
        return has_content_filter

    def listSiblings(self):
        current_object = aq_inner(self.context)
        this_country = current_object.title
        object_ids = current_object.objectIds()
        type_filter = self.getRequestParam(PARAM_CONTENT_FILTER)
        show_type = TYPE_FILTERS[type_filter]
        olist = []
        
        if show_type == u'Resource':
            resource_container = aq_parent(current_object)
            resource_folder = getattr(resource_container, 'resources-1')
            resource_ids = resource_folder.objectIds()
            
            for res_id in resource_ids:
                obj = getattr(resource_folder, res_id)
                if obj.portal_type == show_type:
                    o_country = getattr(obj,'country')
                    if str(this_country).lower() == str(o_country).lower():
                        olist.append(obj)
        else:
            for oid in object_ids:
                obj = getattr(current_object, oid)
                if obj.portal_type == show_type:
                    olist.append(obj)
        return olist
    
    def getPortalTypeStyle(self, obj):
        style=""
        type_icon = obj.getIcon()
        if type_icon:
            style = "background-image:url('/%s') no-repeat center center;" %(type_icon)
        return style
        
    def getCountryFlag(self):
        country_name = unicode(self.context.Title())
        lang_tool = getToolByName(self.context, u'portal_languages', None)
        countries = lang_tool.getAvailableCountries()
        this_country = filter(lambda x: x[u'name'] == country_name, countries.values())
        if this_country:
            return this_country[0][u'flag']
        else:
            return None

    def getRequest(self):
        return self.request.__dict__
        
    def getDashboardSectionTitle(self):
        type_filter = self.getRequestParam(PARAM_CONTENT_FILTER)
        context_title = SECTION_TITLES[type_filter]
        return context_title

    def getSiblingsOfType(self, meta_type, container, fields = None):
        item_list = []
        object_ids = container.objectIds()
        for oid in object_ids:
            obj = getattr(container, oid)
            if obj.portal_type in meta_type:
                title = obj.Title()
                link = obj.absolute_url()
                field_data = {}
                if fields:
                    for field_name in fields:
                        field_value = getattr(obj, field_name)
                        field_value = format_field(field_value)
                        field_data[field_name] = field_value
                item_list.append((title, link, field_data))
            if len(item_list) >= RECENT_ITEM_COUNT:
                break
        return item_list

    def searchResults(self):
        '''
        This does not fetch results as desired
        We use getSiblingsFromLocation instead
        '''
        current_object = aq_inner(self.context)
        results = self.context.portal_catalog(
            path = RESOURCES_PATH,
            country = current_object.title,
            limit = 20,
            sort_on = 'Date',
            review_state = 'published'
        )
        return results

    def getSiblingsFromLocation(self, meta_type, location, which, fields = None):
        item_list = []
        current_object = aq_inner(self.context)
        the_country = current_object.title
        portal_url = getToolByName(self.context, 'portal_url')
        portal = portal_url.getPortalObject()
        try:
            real_location = eval(location)
        except:
            real_location = location
        container = portal.restrictedTraverse(real_location)
        if container:
            if which == ITEMS_RECENT:
                object_ids = container.objectIds()
                for obj_id in object_ids:
                    obj = getattr(container, obj_id)
                    if obj.portal_type in meta_type:
                        obj_country = getattr(obj, 'country')
                        if obj_country.lower() == the_country.lower():
                            field_data = {}
                            if fields:
                                for field_name in fields:
                                    field_value = getattr(obj, field_name)
                                    field_value = format_field(field_value)
                                    field_data[field_name] = field_value
                            item_list.append((obj.title, 
                            obj.absolute_url(), field_data))
                    if len(item_list) >= RECENT_ITEM_COUNT:
                        break
        return item_list

    def  getRecentItems(self):
        """ 
        List the recent content in Country Dashboard 
        Based on recent item filters and filter methods
        """
        current_object = aq_inner(self.context)
        item_listing = []
        
        for filter_item in RECENT_ITEM_FILTERS:
            this_list = dict()
            this_list['title'] = filter_item[2]
            this_list['rend_id'] = filter_item[3]
            this_list['extra_fields'] = filter_item[4]
            this_list['section_header'] = filter_item[5] and filter_item[2]
            #get all items for current type
            method, ident = filter_item[1].split(':')
            extra_fields = filter_item[4]
            meta_type = filter_item[0]
            if method == 'SKIP':
                this_list['items'] = []
            elif method == "HERE":
                this_list['items'] = \
                self.getSiblingsOfType(meta_type, current_object, 
                extra_fields)
            elif method == 'LOOKUP':
                this_list['items'] = \
                self.getSiblingsFromLocation(meta_type, ident, 
                ITEMS_RECENT, extra_fields)
            elif method == 'DSPACE_FEED':
                this_list['items'] = self.getRSSFeedItems(REPOSITORY_FEED_URL)
            else:
                this_list['items'] = []
            item_listing.append(this_list)
        return item_listing

    def getRSSFeedItems(self, feed_url):
        from plonetheme.apkntheme.utils.tools import get_host_url
        current_object = aq_inner(self.context)
        country_name = current_object.Title()
        context_id = current_object.getId()
        feed_url = feed_url.replace("@@CONTEXT_TITLE", country_name)
        feed_url = feed_url.replace("@@CONTEXT_ID", context_id)
        host_url = get_host_url(self.request)
        final_feed_url = host_url + feed_url
        feed_items = getRSSItems(final_feed_url)
        
        feed_items_data = [] 
        if feed_items:
            for entry in feed_items:
                try:
                    feed_link = re.findall(u'handle/.*', entry.link)[0]
                except:
                    logger.info("Failed to extract handle from rss entry : %s", entry.link)
                    feed_link = u''
                feed_item_url = REPOSITORY_URL_ROOT + feed_link
                feed_data = (entry.title, feed_item_url, 
                {u'publishDate': entry.updated})
                feed_items_data.append(feed_data)
        return feed_items_data

    def getFeedData(self):
        feed_data = {}
        current_object = aq_inner(self.context)
        try:
            country_code = getattr(current_object, u'meta_country_code')
        except AttributeError:
            country_code = u''
        lang_code = u'en'
        country_name = current_object.Title()
        rss_url = ANM_FEED_URL %(country_name, lang_code)
        if hasattr(current_object, u'meta_feed_source'):
            rss_url = getattr(current_object, u'meta_feed_source') \
            %(country_code, lang_code)
        
        feed_title = _("apkn_rss_feed_title_country_folders",
        default = "${country_name} News Feed - ANM",
        mapping = {u'country_name': country_name})
        
        feed_data['feed_url'] = rss_url
        feed_data['feed_title'] = feed_title
        feed_data['dom_id'] = random_string()
        feed_data['news_url'] = self.getNewsURL()
        return feed_data

    @ram.cache(compute_request_cache_key)
    def getFeedItems(self):
        '''
        get a list of dictionaries of feed items
        with keys: title, link
        '''
        logger.info("DASHBOARD: Getting Feed Items. \
        This should be cached for a period of time")
        items = []
        current_object = aq_inner(self.context)
        try:
            country_code = getattr(current_object, u'meta_country_code')
        except AttributeError:
            country_code = u''
        lang_code = u'en'
        country_name = current_object.Title()
        
        rss_url = ANM_FEED_URL %(country_name, lang_code)
        if hasattr(current_object, u'meta_feed_source'):
            rss_url = getattr(current_object, u'meta_feed_source') \
            %(country_code, lang_code)
            
        try:
            feed_content = pq(rss_url)
            feed_items = pq('item', pq(feed_content))
            for item in feed_items:
                link = pq('link', pq(item))
                title = pq('title', pq(item))
                link_text = pq(link).text()
                title_text = pq(title).text()
                items.append({'title':title_text,'link': link_text})
                if len(items) > RECENT_ITEM_COUNT:
                    break
        except Exception, e:
            logger.error("Failed to load news Feed for country %s.\
             Error @@  %s", country_name, e.__str__())
        return items

    def getNewsURL(self):
        current_object = aq_inner(self.context)
        try:
            country_code = getattr(current_object, u'meta_country_code')
        except AttributeError:
            country_code = u''
        lang_code = u'en'
        news_url = ANM_NEWS_URL %(lang_code, country_code.upper())
        return news_url

class countryFolderRoot(BrowserView):
    '''
    Render Content for all countries
    filtered by type
    '''
    def getSiblings(self):
        all_ids = self.context.objectIds()
        folders = []
        for oid in all_ids:
            obj = getattr(self.context, oid)
            if obj.meta_type == u'ATFolder' and obj.Title() != '':
                folders.append(obj)
        contentMap = []
        for folder in folders:
            folder_id = folder.getId()
            folder_url = folder.absolute_url()
            folder_title = folder.Title()
            flag = self.getCountryFlag(folder)
            children = self.getContextLinkItem(folder)
            this_map = (folder_title, folder_url, children, flag)
            contentMap.append(this_map)
        return contentMap

    def getSiblingsOfType(self, meta_type, container):
        item_list = []
        object_ids = container.objectIds()
        for oid in object_ids:
            obj = getattr(container, oid)
            if obj.portal_type in meta_type:
                title = obj.Title()
                link = obj.absolute_url()
                item_list.append((title, link))
            if len(item_list) >= RECENT_ITEM_COUNT:
                break
        return item_list



    def getContextLinkItem(self, folder):
        '''
        Gets the menu items for country the current country folder
        See: COUNTRY_CONTEXT_MENU defined at the top of this module
        '''
        CONTEXT_ID = folder.id
        CONTEXT_TITLE = folder.Title()
        url_action = self.validateParam(PARAM_CONTENT_FILTER,
        ALLOWED_DASHBOARD_ACTIONS)
        context_link_data = None
        if url_action:
            cmenu = filter(lambda x: x[4] == url_action, 
                        COUNTRY_CONTEXT_MENU)[0]
            link = cmenu[1]
            link = link.replace(u'@@CONTEXT_ID', CONTEXT_ID)
            link = link.replace(u'@@CONTEXT_TITLE', CONTEXT_TITLE)
            
            if cmenu[2]:
                content_items = self.getSiblingsOfType(cmenu[2], 
                folder)
                if len(content_items) == 1:
                    link = content_items[0][1]
                else:
                    link = None
            
            show = cmenu[3]
            if (not show) and (self.isUserAnonymous()):
                pass
            else:
                context_link_data = {'title': cmenu[0], 'link': link}
        return context_link_data


    def filterTypes(self, parent):
        matched_objects = []
        url_action = self.validateParam(PARAM_CONTENT_FILTER,
        ALLOWED_DASHBOARD_ACTIONS)
        if url_action:
            filter_type = TYPE_FILTERS[url_action]
            oids = parent.objectIds()
            for id in oids:
                obj = getattr(parent, id)
                if obj.portal_type == filter_type:
                    ob_data = {}
                    if obj.Title() in REPLACE_TITLE:
                        ob_data[u'title'] = aq_parent(obj).Title()
                    else:
                        ob_data[u'title'] = obj.Title()
                    ob_data[u'url'] = obj.absolute_url()
                    matched_objects.append(ob_data)
        return matched_objects

    def getRequestParam(self, paramName):
        param = self.request.form.get(paramName,None)
        return param
        
    def validateParam(self, paramName, filterValues):
        param = self.getRequestParam(paramName)
        if param in filterValues:
            return param
        else:
            return None

    def getCountryFlag(self, folder):
        country_name = unicode(folder.Title())
        lang_tool = getToolByName(self.context, u'portal_languages', None)
        countries = lang_tool.getAvailableCountries()
        this_country = filter(lambda x: x[u'name'] == country_name, countries.values())
        if this_country:
            return this_country[0][u'flag']
        else:
            return None

    def getDashboardSectionTitle(self):
        type_filter = self.getRequestParam(PARAM_CONTENT_FILTER)
        context_title = SECTION_TITLES[type_filter]
        return context_title



class FolderTreeStrategy(NavtreeStrategyBase):
    '''
    Navigation strategy for generated folder tree
    '''
    def decoratorFactory(self, node):
        #hack to exclude Profiles Folders from Navigation
        node['purge_from_nav'] = False
        if unicode(node['item'].Title, errors='replace') == u'Profiles':
            node['purge_from_nav'] = True
        return node
    
class BrowseParliamentaryProfiles(BrowserView):
    '''
    Renders search form and a hierarchical directory listing
    of parliametary profiles
    '''
    def buildSearchQuery(self, language_off = False):
        search_query = {}
        search_query['path'] = self.getSearchPath()
        search_query['Type'] = self.getSearchTypes()
        if language_off:
            search_query['Language'] = ''
        return search_query

    def searchSubmitted(self):
        return self.request.form.get(SEARCH_BUTTON_PARAM, None)

    def getSearchQuery(self):
        return self.buildSearchQuery(language_off = True)

    @memoize
    def searchResults(self):
        '''
        This returns a folder tree of the search results for easier
        browsing. The structure of the search query can be extended
        to customize the results through sorts, limits e.t.c
        Look at Products.ZCatalog for details
        '''
        search_query = self.getSearchQuery()
        strategy = FolderTreeStrategy()
        return buildFolderTree(self.context, 
                                query=search_query, 
                                strategy = strategy)

    def getSearchTypes(self):
        '''
        override this to search other object types
        '''
        return PARLIAMENTARY_PROFILES_TYPES

    def getSearchPath(self):
        '''
        Override this method to use a different strategy to generate the
        search path. This assumes that the view's container is the 
        search path we are interested in.
        '''
        search_path = ''
        current_object = aq_inner(self.context)
        if current_object:
            search_path = '/'.join(current_object.getPhysicalPath())
        else:
            portal_tool = self.context.portal_url
            portal_object = portal_tool.getPortalObject()
            search_path = '/'.join(portal_object.getPhysicalPath())
        return search_path


class BrowseParliamentaryContacts(BrowseParliamentaryProfiles):
    '''
    Returns a folder tree of contacts for each or all countries
    '''
    def getSearchTypes(self):
        return COUNTRY_CONTACTS_TYPES

    def getSearchQuery(self):
        return self.buildSearchQuery(language_off = True)


class AdvancedSearch(BrowserView):
    """Country folder advanced search view
    """
    _TYPE_MAPPINGS = {
        "ppf": (_("Parliamentary Profiles"), PARLIAMENTARY_PROFILES_BASE_TYPES),
        "ors": (_("Online Resources"), RESOURCE_CONTENT_TYPES_BASE),
        "cts": (_("Contacts"), COUNTRY_CONTACTS_TYPES_BASE),
    }
    
    show_term_filters = False
    
    @property
    def all_types(self):
        return list(
            itertools.chain(
                *[ t[1] for t in self._TYPE_MAPPINGS.itervalues() ]
            )
        )

    @property
    def page_action(self):
        return self.__name__

    @property
    def catalog(self):
        return getToolByName(self.context, "portal_catalog")

    @property
    def country_folder_url(self):
        return "/".join(self.context.getPhysicalPath())

    @property
    @memoize
    def country_data(self):
        form_country = self.request.form.get("country", None)
        return [ { "id": c[0], 
                   "title":_(c[1].title),
                   "selected": c[0] == form_country
            }
            for c in self.context.items() if hasattr(c[1], COUNTRY_FOLDER_META)
        ]

    @property
    def type_data(self):
        form_type = self.request.form.get("portal_type", None)
        return [
            { "id": pk, 
              "title": pv[0], 
              "selected": (pk == form_type) if self.search_submitted else "selected"
            }
            for pk,pv in self._TYPE_MAPPINGS.iteritems()
        ]
        
    @property
    def portal_types_to_search(self):    
        form_type = self.request.form.get("portal_type", None)
        return[
            { "id": item, 
              "title": item, 
              "selected": (item == form_type) if self.search_submitted else "selected"
            }
            for key in self._TYPE_MAPPINGS.keys()
            for item in self._TYPE_MAPPINGS[key][1]
        ]         

    @property
    def search_submitted(self):
        return self.request.form.get(SEARCH_BUTTON_PARAM, None)

    @property
    def here_url(self):
	"""
	Test to get the full page URL
	"""
	context = aq_inner(self.context)
        context_state = getMultiAdapter((context, self.request), name=u'plone_context_state')
	url = context_state.current_page_url()
        return url

    @property
    def url_query_params(self):
	"""
	Get the query parameters
	"""
	log.info("Getting the search parameters: %s", self.queryParams())
        results = self.queryParams()
	
	param_String = ""	
	for curr_param in results: 
	    if curr_param == "portal_type":
	        """This is a list and not a string, so it should be handled differently.
		"""
		for type_value in results[curr_param]:
		    param_String += curr_param + '=' + type_value + '&'	
	    elif curr_param == "SearchableText":
		"""Ignore this part as it will be added to the URL directly.
		"""	
	    else:
		param_String += curr_param + '=' + results[curr_param] + '&'		
	
        return param_String

    @property
    def show_type_filter(self):
        return len(self._TYPE_MAPPINGS.keys()) > 1 

    @property
    def search_types_i18n(self):
        if len(self._TYPE_MAPPINGS) > 1:
            return " - ".join(
                [ td[0] for td in self._TYPE_MAPPINGS.itervalues() ]
            )
        else:
            return self._TYPE_MAPPINGS.values()[0][0]

    def extendPath(self, extra):
        return "/".join((self.country_folder_url, extra))

    def get_form_data(self):
        return {
            "SearchableText": self.request.form.get("SearchableText", ""),
            "match_exact_phrase": self.request.form.get("match_exact_phrase", 
                False
            ),
        }

    def queryParams(self):
        _SKIP_FIELDS = ["match_exact_phrase", SEARCH_BUTTON_PARAM]
        """Dict of kwargs to pass to catalog
        """
        params = {}
        params["path"] = self.country_folder_url
        params["sort_on"] = u"path"
        params["sort_order"] = "descending"
        for k, v in self.request.form.iteritems():
            if k in _SKIP_FIELDS:
                continue
            if v not in [None, u'']:
                params[k] = v
#	import pdb; pdb.set_trace()
        return self.sanitizeParams(params)

    def sanitizeParams(self, params):
        VALID_KEYS = self._TYPE_MAPPINGS.keys()
        if "portal_type" in params.keys():
            keys = params["portal_type"]
            if type(keys) != list:
                keys = [keys]
            if set(keys).issubset(set(VALID_KEYS)):
                params["portal_type"] = list(itertools.chain(
                    *[self._TYPE_MAPPINGS[pk][1] for pk in keys if pk in VALID_KEYS]
                ))                                                           
        else:
            params["portal_type"] = self.all_types
             
        if "country" in params:
            params["path"] = self.extendPath(params["country"])
            params.pop("country")
        if "SearchableText" in params:
            if self.request.form.get("match_exact_phrase", None):
                params["SearchableText"] = "\"%s\"" %  params["SearchableText"]
        return params

    def searchMessage(self, kw):
        return _("advanced_search_results_message", 
            default=u"Found $count items - showing $start through $end.",
            mapping = kw
        ) if (kw.get("count", 0) > 0)  else _("No items found.")

    def exec_query(self, params):
        results = self.catalog(params)
        start = self.request.get("b_start", 0)
        return Batch(results, RECENT_ITEM_COUNT, int(start), orphan=0)

    def searchResults(self):
        country_meta = []
        def _add_country_data(brain):
            country_data = None
            try:
                index = self.catalog._catalog.getIndex(COUNTRY_FOLDER_META)
                c_code = index.getEntryForObject(brain.getRID(), "")
                if c_code:
                    country_data = countries.getCountries().get(c_code, None)
            except IndexError:
                log.error("Index %s does not exist.", COUNTRY_FOLDER_META)
            country_meta.append(country_data)

        log.info("Performing search with params: %s", self.queryParams())
        results = self.exec_query(self.queryParams())
        map(_add_country_data, results)
        kw = {"count": results.sequence_length, 
            "start": results.start,
            "end": results.start + len(results)-1
        }
        return {
            "search_message": self.searchMessage(kw), 
            "search_results": results,
            "country_meta": country_meta
        }
        

class AdvancedSearchResources(AdvancedSearch):
    """Search online resources across countries - Subject filters provided
    """
    _TYPE_MAPPINGS = {
        "ors": (_("Online Resources"), RESOURCE_CONTENT_TYPES_BASE),
    }
    
    show_term_filters = True
    FILTER_KEYS = [
        {u"name": _("Subjects"), u"index": u"resourcesubjectindex" },
    ]

    @memoize
    def get_filter_terms(self, **kw):
        """Return catalog indices of unique index values
        """
        query = {"path":self.country_folder_url, "portal_type": self.all_types}
        catalog_items = self.catalog(query)
        terms = [record.resourcesubject for record in catalog_items]
        terms_combined = list(
            itertools.chain(*terms)
        )
        term_uniques = list(set(terms_combined))
        filter_terms = [{"id":ft ,"title": RESOURCESUBJECTS.getValue(ft)}
            for ft in term_uniques if ft not in ['']
        ]
        return filter_terms

    @memoize
    def meta_filters(self):
        """Filter terms with navigation constants
        """
        filters = list()
        for filter_key in self.FILTER_KEYS:
            filter_name = filter_key.get("name")
            filter_id = filter_key.get("index")
            filter_url = "%s?%s=GO&%s=" % (self.page_action, 
                SEARCH_BUTTON_PARAM, filter_key.get("index")
            )
            filter_terms = self.get_filter_terms()
            filter = dict(filter_id=filter_id, filter_name=filter_name, 
                filter_url=filter_url, filter_terms=filter_terms
            ) 
            filters.append(filter)
        return filters


class AdvancedSearchContacts(AdvancedSearch):
    _TYPE_MAPPINGS = {
        "cts": (_("Contacts"), COUNTRY_CONTACTS_TYPES_BASE),
    }
